import React, { useEffect, useRef, useState } from "react";
import classNames from "classnames";
import TreeNode, { KeyNodeMap } from "./TreeNode";
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";

export interface TreeData {
  name: string;
  key: string;
  type: string;
  collapsed: boolean;
  children?: TreeData[];
  parent?: TreeData;
  checked?: boolean;
  icon?: IconDefinition;
  loading?: boolean;
}

export interface TreeProps {
  data: TreeData;
  checkable?: boolean;
  requestData?: (key: string) => Promise<TreeData[]>;
  onselect?: (key: string) => void;
  selectKey?: string;
  // virtualSize?: number;
}
const Tree = (props: TreeProps) => {
  const { data, checkable, requestData, onselect, selectKey } =
    props;
  const [keyNodeMap, setKeyNodeMap] = useState({} as KeyNodeMap);
  const treeRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    buildKeyMap();
    // if (virtualSize) {
    //   let tree = treeRef.current;
    //   if (tree) {
    //     let treeNode: HTMLDivElement | null = tree.querySelector(".inner");
    //     if (treeNode !== null) {
    //       tree.style.height = `${virtualSize * treeNode.clientHeight}px`;
    //     }
    //   }
    // }
  }, []);
  const [selectedKey, setSelectedKey] = useState(selectKey);
  let nodeMap: KeyNodeMap = {};
  const buildKeyMap = () => {
    nodeMap[data.key] = data;
    if (data.children && data.children.length > 0) {
      walk(data.children, data);
    }
    setKeyNodeMap(() => {
      return nodeMap;
    });
  };
  const walk = (children: TreeData[], parent: TreeData) => {
    children.forEach((item: TreeData) => {
      item.parent = parent;
      nodeMap[item.key] = item;
      if (item.children && item.children.length > 0) {
        walk(item.children, item);
      }
    });
  };
  const onCollapse = async (key: string) => {
    let data = keyNodeMap[key];
    if (data) {
      let { children } = data;
      if (children) {
        data.collapsed = !data.collapsed;
        setKeyNodeMap(() => {
          return { ...keyNodeMap };
        });
      } else {
        if (requestData) {
          data.loading = true;
          setKeyNodeMap(() => {
            return { ...keyNodeMap, data };
          });
          // data.children = await requestData(key);
          console.log("await requestData(key)", await requestData(key));
          setTimeout(() => {
            data.children = [
              {
                name: data.name + "son1",
                key: `${data.key}-1`,
                type: "folder",
                collapsed: true,
              },
              {
                name: data.name + "son2",
                key: `${data.key}-2`,
                type: "file",
                collapsed: true,
              },
            ];

            data.loading = false;
            data.collapsed = false;
            buildKeyMap();
          }, 2000);
        }
      }
    }
  };
  const checkChildren = (children: TreeData[] = [], checked: boolean) => {
    children.forEach((item) => {
      item.checked = checked;
      if (item.children && item.children.length > 0) {
        checkChildren(item.children, checked);
      }
    });
  };
  const checkParent = (parent: TreeData) => {
    while (parent) {
      parent.checked =
        parent.children &&
        parent.children.every((item: TreeData) => item.checked);
      parent = parent.parent!;
    }
  };
  const onCheck = (key: string, checked: boolean) => {
    let data = keyNodeMap[key];
    if (data) {
      data.checked = checked;
      if (data.checked) {
        checkChildren(data.children, true);
        checkParent(data.parent!);
      } else {
        checkChildren(data.children, false);
        checkParent(data.parent!);
      }

      setKeyNodeMap(() => {
        return { ...keyNodeMap, data };
      });
    }
  };

  return (
    <div className="coerger-tree" ref={treeRef}>
      <div className="tree-nodes">
        <TreeNode
          data={data}
          onCollapse={onCollapse}
          onCheck={onCheck}
          checkable={checkable}
          requestData={requestData}
          onselect={onselect}
          selectedKey={selectedKey}
          setSelectedKey={setSelectedKey}
          // virtualData={keyNodeMap}
        ></TreeNode>
      </div>
    </div>
  );
};

export default Tree;
